#include <stdio.h>
#include <stdlib.h>
#include "tac.h"

//Cara, não sei se o mais adequado aqui é usar hash_nodes ou hash_entries

TAC *tac_create(int type, HASH_NODE *res, HASH_NODE *op1, HASH_NODE *op2) {
    TAC *new;
    new = calloc(1, sizeof (TAC));
    new->type = type;
    new->res = res;
    new->op1 = op1;
    new->op2 = op2;
    new->next = 0;
    new->prev = 0;
    return new;
}

TAC *tac_join(TAC *l1, TAC *l2) {
    TAC *p;
    if (!l1) return l2;
    if (!l2) return l1;
    for (p = l2; p->prev; p = p->prev)
        ;
    p->prev = l1;
    l1->next = p;
    return l2;
}

void tac_reverse(TAC *list) {
    if(list)
    {
        TAC *aux = list->next;
        list->next = list->prev;
        list->prev = aux;
        tac_reverse(list->next);
    }
}

TAC* tac_get_first(TAC *list) {
    TAC* aux = list;
    while(aux->next)
        aux = aux->next;
    return aux;
}

void tac_print(TAC *list) {
    printf("\n\n===== <TAC> =====\n");
    TAC *p;
    for (p = list; p; p = p->prev) {
        tac_print_single(p);
    }
    printf("===== </TAC> =====\n\n");
}

void tac_print_single(TAC *t) {
    printf("TAC(");
    switch (t->type) {
        case TAC_ADD: printf("TAC_ADD");
            break;
        case TAC_SUB: printf("TAC_SUB");
            break;
        case TAC_MUL: printf("TAC_MUL");
            break;
        case TAC_DIV: printf("TAC_DIV");
            break;
        case TAC_SYMBOL: printf("TAC_SYMBOL");
            break;
        case TAC_COPY: printf("TAC_COPY");
            break;
        case TAC_JZERO: printf("TAC_JZERO");
            break;
        case TAC_LABEL: printf("TAC_LABEL");
            break;
        case TAC_GE: printf("TAC_GE");
            break;
        case TAC_LE: printf("TAC_LE");
            break;
        case TAC_NE: printf("TAC_NE");
            break;
        case TAC_EQ: printf("TAC_EQ");
            break;
        case TAC_LESS: printf("TAC_LESS");
            break;
        case TAC_GRT: printf("TAC_GRT");
            break;
        case TAC_AND: printf("TAC_AND");
            break;
        case TAC_OR: printf("TAC_OR");
            break;
        case TAC_GOTO: printf("TAC_GOTO");
            break;
        case TAC_CALL: printf("TAC_CALL");
            break;
        case TAC_NOT: printf("TAC_NOT");
            break;
        case TAC_VEC: printf("TAC_VEC");
            break;
        case TAC_PRINT_INT: printf("TAC_PRINT_INT");
            break;
        case TAC_RETURN: printf("TAC_RETURN");
            break;
        case TAC_ARG: printf("TAC_ARG");
            break;
        case TAC_FUNC_BEGIN: printf("TAC_FUNC_BEGIN");
            break;
        case TAC_FUNC_END: printf("TAC_FUNC_END");
            break;
        case TAC_FUNC_PARAM: printf("TAC_FUNC_PARAM");
            break;
        case TAC_REF: printf("TAC_REF");
            break;
        case TAC_INT_TYPE: printf("TAC_INT_TYPE");
            break;
        case TAC_BYTE_TYPE: printf("TAC_BYTE_TYPE");
            break;
        case TAC_VAR_DEF: printf("TAC_VAR_DEF");
            break;
        case TAC_VEC_DEF: printf("TAC_VEC_DEF");
            break;
        case TAC_VEC_REF: printf("TAC_VEC_REF");
            break;
        case TAC_VEC_COPY: printf("TAC_VEC_COPY");
            break;
        case TAC_PRINT_STR: printf("TAC_PRINT_STR");
            break;
        default: printf("unknown");
            break;
    }
    if (t->res) printf(", %s", t->res->data->lexeme);
    if (t->op1) printf(", %s", t->op1->data->lexeme);
    if (t->op2) printf(", %s", t->op2->data->lexeme);
    printf(")\n");
}


